package ua.diploma.registration;

import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import ua.diploma.core.Constants;
import ua.diploma.core.ServiseFactory;
import ua.diploma.hibernate.dto.SecretQuestion;
import ua.diploma.hibernate.dto.User;
import ua.diploma.user.UserBean;

/**
 * Контороллер регистрации и авторизации
 * 
 * @author netstalk3r
 * 
 */
@WebServlet(name = "registration", urlPatterns = { "/private/registration" })
public class RegistrationController extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final String ACTION_REGISTRATION = "registration";
	private static final String ACTION_ACTIVATION = "activation";

	private static final String PARAM_LOGIN = "login";
	private static final String PARAM_EMAIL = "email";
	private static final String PARAM_PASSWORD = "password";
	private static final String PARAM_HASH = "hash";
	private static final String PARAM_FIRST_NAME = "firstName";
	private static final String PARAM_SECOND_NAME = "secondName";
	private static final String PARAM_CONFIRM_PASSWORD = "confirmPassword";
	private static final String PARAM_SEX = "sex";
	private static final String PARAM_SECRET_QUESTION = "secretQuestion";
	private static final String PARAM_ANSWER = "answer";

	private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

	private static final String VALIDATION_ERROR_LOGIN_USED = "Логин занят";
	private static final String VALIDATION_EMAIL_INCORRECT = "Неверный email";
	private static final String VALIDATION_EMAIL_USED = "Email занят";
	private static final String VALIDATION_SYSTEM_ERROR = "Невозможно создать пользователя";

	/**
	 * логгер
	 */
	private static final Logger log = Logger
			.getLogger(RegistrationController.class);

	/**
	 * Конструктор по умолчанию
	 */
	public RegistrationController() {
		super();
	}

	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		log.info("RegistrationController работает");
		final String action = request.getParameter(Constants.ACTION_PARAM);
		log.info("RegistrationController ---> action = " + action);
		if (action == null) {
			request.getRequestDispatcher(Constants.LOGIN_VIEW).forward(request,
					response);
			return;
		}
		if (action.equals(ACTION_REGISTRATION)) {
			String login = request.getParameter(PARAM_LOGIN);
			String password = request.getParameter(PARAM_PASSWORD);
			String confirmPassword = request
					.getParameter(PARAM_CONFIRM_PASSWORD);
			String email = request.getParameter(PARAM_EMAIL);

			// Данные ответа;
			Boolean isValid = false;

			RegistrationService registrationServise = ServiseFactory
					.getRegistrationService();
			ArrayList<String> validationErrors = validate(login, password,
					confirmPassword, email, registrationServise);

			if (validationErrors.size() > 0) {
				// если есть ошибки валидации, отправляем пользователю
				request.setAttribute("isValid", isValid);
				request.setAttribute("errors", validationErrors);
				request.getRequestDispatcher(Constants.VALID_JSON_REGISTRATION_VIEW)
						.forward(request, response);
				return;
			} else {
				// если ошибок нет, регистрируем пользователя
				String firstName = request.getParameter(PARAM_FIRST_NAME);
				String secondName = request.getParameter(PARAM_SECOND_NAME);
				String sex = request.getParameter(PARAM_SEX);
				String Question = request.getParameter(PARAM_SECRET_QUESTION);
				SecretQuestion secretQuestion = new SecretQuestion(Question);
				String answer = request.getParameter(PARAM_ANSWER);

				User user = new User();
				user.setLogin(login);
				user.setPassword(password);
				user.setEmail(email);
				user.setStatus(Constants.AccoutStaus.REGISTERED.getValue());
				user.setFirstName(firstName);
				user.setSecondName(secondName);
				user.setGender(Boolean.valueOf(sex));
				user.setSecretQuesion(secretQuestion);
				user.setSecretAnswer(answer);

				try {
					registrationServise.registerUser(user);
				} catch (RegistrationException e) {
					validationErrors.add(VALIDATION_SYSTEM_ERROR);
				}
				if (validationErrors.size() == 0) {
					isValid = true;
				}
				request.setAttribute("isValid", isValid);
				request.setAttribute("errors", validationErrors);
				request.getRequestDispatcher(Constants.VALID_JSON_REGISTRATION_VIEW)
						.forward(request, response);
				return;
			}
		} else if (action.equals(ACTION_ACTIVATION)) {
			final String hash = request.getParameter(PARAM_HASH);
			RegistrationService registrationServise = ServiseFactory
					.getRegistrationService();
			try {
				User user = registrationServise.activateAccount(hash);
				if (user != null) {
					UserBean userBean = (UserBean) request.getSession()
							.getAttribute(Constants.USER_BEAN_ATTRIBUTE);
					request.setAttribute("message", "Аккаунт активирован.");
					if (userBean == null) {
						request.getRequestDispatcher(Constants.LOGIN_VIEW)
								.forward(request, response);
					} else {
						request.getRequestDispatcher(Constants.CHAT_VIEW)
								.forward(request, response);
					}
				} else {
					request.setAttribute("errorMessage", "Сcылка не активна.");
					request.getRequestDispatcher(Constants.ERROR_CONTEROOLER)
							.forward(request, response);
				}
				return;
			} catch (ActivationException e) {
				log.error("Ошибка активации", e);
				request.setAttribute("errorMessage", "Ошибка активации.");
				request.getRequestDispatcher(Constants.ERROR_CONTEROOLER)
						.forward(request, response);
			}
			return;
		}
	}

	private static ArrayList<String> validate(String login, String password,
			String confirmPassword, String email,
			RegistrationService registrationServise) {
		ArrayList<String> validationError = new ArrayList<String>();

		// валидация логина
		if (login.length() < Constants.MIN_LOGIN_LENGHT) {
			validationError.add(Constants.VALIDATION_ERROR_LOGIN_LENGTH);
		}
		if (registrationServise.getUserByLogin(login) != null) {
			validationError.add(VALIDATION_ERROR_LOGIN_USED);
		}

		// валидация email'a
		if (!verifivationEmail(email)) {
			validationError.add(VALIDATION_EMAIL_INCORRECT);
		}
		if (registrationServise.getUserByEmail(email) != null) {
			validationError.add(VALIDATION_EMAIL_USED);
		}

		// валидация пароля
		if (!password.equals(confirmPassword)) {
			validationError.add(Constants.VALIDATION_ERROR_PASSWORD_CONFIRM);
		}
		if (password.length() < Constants.MIN_PASS_LENGHT) {
			validationError.add(Constants.VALIDATION_ERROR_PASSWORD_LENGTH);
		}
		return validationError;
	}

	private static boolean verifivationEmail(final String email) {
		Pattern pattern = Pattern.compile(EMAIL_PATTERN);
		Matcher matcher = pattern.matcher(email);
		return matcher.matches();
	}

}
